#pragma once


#include "instructions/base/instructions.h"
#include "instructions/comparisons/comparisons.h"
#include "instructions/constants/nop.hpp"
#include "instructions/constants/ipush.h"
#include "instructions/constants/const.h"
#include "instructions/control/control.h"
#include "instructions/conversions/conversions.h"
#include "instructions/extended/extended.h"
#include "instructions/loads/aload.h"
#include "instructions/loads/dload.h"
#include "instructions/loads/fload.h"
#include "instructions/loads/iload.h"
#include "instructions/loads/lload.h"
#include "instructions/math/math_instructions.h"
#include "instructions/stack/dup.h"
#include "instructions/stack/pop.h"
#include "instructions/stack/swap.h"
#include "instructions/stores/astore.h"
#include "instructions/stores/dstore.h"
#include "instructions/stores/fstore.h"
#include "instructions/stores/istore.h"
#include "instructions/stores/lstore.h"



namespace jvm {
namespace instructions {

    class InstructionFactory {
        private:
            // 单例指令对象
            static const NOP nop;
            static const ACONST_NULL aconst_null;
            static const ICONST_M1 iconst_m1;
            static const ICONST_0 iconst_0;
            static const ICONST_1 iconst_1;
            static const ICONST_2 iconst_2;
            static const ICONST_3 iconst_3;
            static const ICONST_4 iconst_4;
            static const ICONST_5 iconst_5;
            static const LCONST_0 lconst_0;
            static const LCONST_1 lconst_1;
            static const FCONST_0 fconst_0;
            static const FCONST_1 fconst_1;
            static const FCONST_2 fconst_2;
            static const DCONST_0 dconst_0;
            static const DCONST_1 dconst_1;
            
            // 加载指令单例
            static const ILOAD_0 iload_0;
            static const ILOAD_1 iload_1;
            static const ILOAD_2 iload_2;
            static const ILOAD_3 iload_3;
            static const LLOAD_0 lload_0;
            static const LLOAD_1 lload_1;
            static const LLOAD_2 lload_2;
            static const LLOAD_3 lload_3;
            static const FLOAD_0 fload_0;
            static const FLOAD_1 fload_1;
            static const FLOAD_2 fload_2;
            static const FLOAD_3 fload_3;
            static const DLOAD_0 dload_0;
            static const DLOAD_1 dload_1;
            static const DLOAD_2 dload_2;
            static const DLOAD_3 dload_3;
            static const ALOAD_0 aload_0;
            static const ALOAD_1 aload_1;
            static const ALOAD_2 aload_2;
            static const ALOAD_3 aload_3;
            
            // 存储指令单例
            static const ISTORE_0 istore_0;
            static const ISTORE_1 istore_1;
            static const ISTORE_2 istore_2;
            static const ISTORE_3 istore_3;
            static const LSTORE_0 lstore_0;
            static const LSTORE_1 lstore_1;
            static const LSTORE_2 lstore_2;
            static const LSTORE_3 lstore_3;
            static const FSTORE_0 fstore_0;
            static const FSTORE_1 fstore_1;
            static const FSTORE_2 fstore_2;
            static const FSTORE_3 fstore_3;
            static const DSTORE_0 dstore_0;
            static const DSTORE_1 dstore_1;
            static const DSTORE_2 dstore_2;
            static const DSTORE_3 dstore_3;
            static const ASTORE_0 astore_0;
            static const ASTORE_1 astore_1;
            static const ASTORE_2 astore_2;
            static const ASTORE_3 astore_3;
            
            // 栈操作指令单例
            static const POP pop;
            static const POP2 pop2;
            static const DUP dup;
            static const DUP_X1 dup_x1;
            static const DUP_X2 dup_x2;
            static const DUP2 dup2;
            static const DUP2_X1 dup2_x1;
            static const DUP2_X2 dup2_x2;
            static const SWAP swap;
            
            // 数学运算指令单例
            static const IADD iadd;
            static const LADD ladd;
            static const FADD fadd;
            static const DADD dadd;
            static const ISUB isub;
            static const LSUB lsub;
            static const FSUB fsub;
            static const DSUB dsub;
            static const IMUL imul;
            static const LMUL lmul;
            static const FMUL fmul;
            static const DMUL dmul;
            static const IDIV idiv;
            static const LDIV ldiv;
            static const FDIV fdiv;
            static const DDIV ddiv;
            static const IREM irem;
            static const LREM lrem;
            static const FREM frem;
            static const DREM drem;
            static const INEG ineg;
            static const LNEG lneg;
            static const FNEG fneg;
            static const DNEG dneg;
            
            // 位运算指令单例
            static const ISHL ishl;
            static const LSHL lshl;
            static const ISHR ishr;
            static const LSHR lshr;
            static const IUSHR iushr;
            static const LUSHR lushr;
            static const IAND iand;
            static const LAND land;
            static const IOR ior;
            static const LOR lor;
            static const IXOR ixor;
            static const LXOR lxor;
            
            // 类型转换指令单例
            static const I2L i2l;
            static const I2F i2f;
            static const I2D i2d;
            static const L2I l2i;
            static const L2F l2f;
            static const L2D l2d;
            static const F2I f2i;
            static const F2L f2l;
            static const F2D f2d;
            static const D2I d2i;
            static const D2L d2l;
            static const D2F d2f;
            static const I2B i2b;
            static const I2C i2c;
            static const I2S i2s;
            
            // 比较指令单例
            static const LCMP lcmp;
            static const FCMPL fcmpl;
            static const FCMPG fcmpg;
            static const DCMPL dcmpl;
            static const DCMPG dcmpg;
        
        public:
            static Instruction* newInstruction(uint8_t opcode);
        };

} // namespace instructions
} // namespace jvm
